package com.will.willaicodemother.utils;

import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.microsoft.playwright.Browser;
import com.microsoft.playwright.BrowserType;
import com.microsoft.playwright.Page;
import com.microsoft.playwright.Playwright;
import com.microsoft.playwright.options.WaitUntilState;
import com.will.willaicodemother.exception.BusinessException;
import com.will.willaicodemother.exception.ErrorCode;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.nio.file.Paths;
import java.util.UUID;

/**
 * @author will
 * @since 2025/8/20 08:45
 * 截图工具类
 */
@Slf4j
public class WebScreenshotUtils {

    private static final ThreadLocal<Playwright> playwrightThreadLocal = new ThreadLocal<>();

    static {
        // 注册JVM关闭钩子，确保程序退出时清理资源
        Runtime.getRuntime().addShutdownHook(new Thread(WebScreenshotUtils::shutdown));
    }
    /*
      全局初始化初始化webDriver，避免重复加载
     */
    public static Playwright getPlaywright() {
        Playwright playwright = playwrightThreadLocal.get();
        if (playwright == null) {
            playwright = Playwright.create();
            playwrightThreadLocal.set(playwright);
        }
        return playwright;
    }

    /**
     * 生成网页截图
     * @param url 网页地址
     * @return 压缩后的网页截图保存路径
     */
    public static String saveWebPageScreenshot(String url) {
        // 非空校验
        if (StrUtil.isBlank(url)){
            log.error("网页截图失败，url为空");
            return null;
        }
        Page page = null;
        Browser browser = null;
        try {
            // 创建临时目录
            String rootPath = System.getProperty("user.dir") + "/tmp/screenshots/" + UUID.randomUUID().toString().substring(0, 8);
            FileUtil.mkdir(rootPath);
            // 图片后缀
            final String IMAGE_SUFFIX = ".png";
            // 原始图片保存路径
            String imageSavePath = rootPath + File.separator + RandomUtil.randomNumbers(5) + IMAGE_SUFFIX;
            // 访问网页
            Playwright playwright = getPlaywright();
            browser = playwright.chromium().launch(new BrowserType.LaunchOptions()
                    .setHeadless(true));// 无头模式
            // 创建页面
            page = browser.newPage();
            // 打开网页
            // 等待页面加载完成（等待网络空闲或加载状态）
            page.navigate(url, new Page.NavigateOptions()
                    .setWaitUntil(WaitUntilState.NETWORKIDLE));
            // 截图
            // 截取全屏
            page.screenshot(new Page.ScreenshotOptions()
                    .setPath(Paths.get(imageSavePath))
                    .setFullPage(false));
            // 保存原始图片
            log.info("原始图片保存成功: {}", imageSavePath);
            // 压缩图片
            String COMPRESS_SUFFIX = ".jpg";
            String compressedImagePath = rootPath + File.separator + RandomUtil.randomNumbers(5) + COMPRESS_SUFFIX;
            compressImage(imageSavePath, compressedImagePath);
            // 删除原始图片
            FileUtil.del(imageSavePath);
            return compressedImagePath;
        } catch (Exception e) {
            return null;
        }finally {
            // 确保页面和浏览器实例关闭
            if (page != null) {
                try {
                    page.close();
                } catch (Exception e) {
                    log.warn("关闭Page失败", e);
                }
            }
            if (browser != null) {
                try {
                    browser.close();
                } catch (Exception e) {
                    log.warn("关闭Browser失败", e);
                }
            }
        }
    }

    /**
     * 保存图片到文件
     */
    private static void saveImage(byte[] imageBytes, String imagePath) {
        try {
            FileUtil.writeBytes(imageBytes, imagePath);
        } catch (Exception e) {
            log.error("保存图片失败: {}", imagePath, e);
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "保存图片失败");
        }
    }

    /**
     * 压缩图片
     */
    private static void compressImage(String originalImagePath, String compressedImagePath) {
        // 压缩图片质量（0.1 = 10% 质量）
        final float COMPRESSION_QUALITY = 0.3f;
        try {
            ImgUtil.compress(
                    FileUtil.file(originalImagePath),
                    FileUtil.file(compressedImagePath),
                    COMPRESSION_QUALITY
            );
        } catch (Exception e) {
            log.error("压缩图片失败: {} -> {}", originalImagePath, compressedImagePath, e);
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "压缩图片失败");
        }
    }

    /**
     * 关闭所有资源
     */
    public static void shutdown() {
        Playwright playwright = playwrightThreadLocal.get();
        if (playwright != null) {
            try {
                playwright.close();
                log.info("Playwright已关闭");
            } catch (Exception e) {
                log.warn("关闭Playwright失败", e);
            } finally {
                playwrightThreadLocal.remove(); // 清理ThreadLocal
            }
        }
    }
}
